package com.heima.wemedia.service.impl;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.apis.article.IArticleClient;
import com.heima.apis.schedule.IScheduleClient;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.schedule.dto.Task;
import com.heima.model.wemedia.dtos.NewsAuthDto;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.pojos.WmMaterial;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmNewsMaterial;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.model.wemedia.vo.WmNewsVo;
import com.heima.utils.ProtostuffUtil;
import com.heima.wemedia.mapper.WmMaterialMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmNewsMaterialMapper;
import com.heima.wemedia.mapper.WmUserMapper;
import com.heima.wemedia.service.AutoScanService;
import com.heima.wemedia.service.WmNewsService;
import com.heima.wemedia.thread.WmUserThreadLocal;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;

@Service
@Slf4j
@Transactional
public class WmNewsServiceImpl  extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    @Autowired
    private WmNewsMapper wmNewsMapper;

    @Autowired
    private WmMaterialMapper wmMaterialMapper;

    @Autowired
    private WmNewsMaterialMapper wmNewsMaterialMapper;

    @Autowired
    private AutoScanService autoScanService;

    @Override
    public PageResponseResult list(WmNewsPageReqDto dto) {

        if (dto == null) {
            return new PageResponseResult(0,0,0);
        }

        Integer currentPage = dto.getPage();
        Integer size = dto.getSize();

        // 构造条件控制器
        LambdaQueryWrapper<WmNews> wrapper = new LambdaQueryWrapper<>();

        //状态
        Short status = dto.getStatus();
        wrapper.eq(status != null,WmNews::getStatus, status);
        //时间
        Date beginPubDate = dto.getBeginPubDate();
        Date endPubDate = dto.getEndPubDate();
        wrapper.between(beginPubDate != null && endPubDate != null,WmNews::getPublishTime,beginPubDate,endPubDate);
        //频道id
        Integer channelId = dto.getChannelId();
        wrapper.eq(channelId != null,WmNews::getChannelId,channelId);
        //关键词
        String keyword = dto.getKeyword();
        wrapper.like(keyword != null,WmNews::getTitle,keyword);
        //用户id
        Integer id = WmUserThreadLocal.get().getId();
        wrapper.eq(WmNews::getUserId,id);
        //排序
        wrapper.orderByDesc(WmNews::getCreatedTime);

        Page<WmNews> page = new Page<>(currentPage,size);
        Page<WmNews> wmNewsPage = wmNewsMapper.selectPage(page, wrapper);
        Long total = wmNewsPage.getTotal();
        PageResponseResult pageResponseResult = new PageResponseResult(currentPage, size, total.intValue());
        pageResponseResult.setData(wmNewsPage.getRecords());

        return pageResponseResult;
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public ResponseResult submit(WmNewsDto wmNewsDto) throws Exception {
        // 1. 提取新闻内容
        WmNews wmNews = getNews(wmNewsDto);
        if (wmNews == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        // 2. 插入新闻表
        int insert = wmNewsMapper.insert(wmNews);
        if (insert < 1) {
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
        }

        // 3. 判断是不是草稿
        if (wmNews.getStatus() == 0) {
            return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
        }
        // 4. 提取内容图
        String content = wmNewsDto.getContent();
        List<String> contentImages = getContentImages(content);
        // 5. 提取封面图
        List<String> images = wmNewsDto.getImages();
        // 6. 自动布局
        List<String> coverImages = getCoverImages(wmNewsDto.getType(), contentImages, images);
        // 7. 添加内容图
        Boolean addMaterial = addMaterial(wmNewsDto.getId(), contentImages, 0);
        if (!addMaterial) {
            throw new RuntimeException("内容图添加失败");
        }
        // 8. 添加封面图
        Boolean addMaterial1 = addMaterial(wmNewsDto.getId(), coverImages, 1);
        if (!addMaterial1) {
            throw new RuntimeException("封面图添加失败");
        }

        Boolean addTaskResult = addToTask(wmNews.getId(), wmNews.getPublishTime().getTime());
        if (!addTaskResult) {
            throw new RuntimeException("任务添加失败");
        }
        //autoScanService.autoScanWmNews(wmNews.getId());
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Autowired
    private KafkaTemplate kafkaTemplate;

    @Override
    public ResponseResult downOrUp(WmNewsDto wmNewsDto) {
        // 0. 判断dto是否为空
        if (wmNewsDto == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        // 1. 获取wmNews
        Integer id = wmNewsDto.getId();
        WmNews wmNews = wmNewsMapper.selectById(id);
        if (wmNews == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
        }
        // 2. 判断wmNews状态是否为已发布
        Short status = wmNews.getStatus();
        if (9 != status) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        // 3. 更新wmNews的enable
        wmNews.setEnable(wmNewsDto.getEnable());
        int updateResult = wmNewsMapper.updateById(wmNews);
        if (updateResult < 1) {
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
        }
        // 4. 向kafka中发送消息
        Map<String,Object> map = new HashMap<>();
        map.put("articleId",wmNews.getId());
        map.put("enable",wmNews.getEnable());
        kafkaTemplate.send("news.down.or.up",JSON.toJSONString(map));

        // 5. 返回结果
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Override
    public ResponseResult findList(NewsAuthDto dto) {
        // 1.参数检查
        dto.checkParam();

        // 2.记录当前页
        int currentPage = dto.getPage();

        // 3.分页查询+count查询
        dto.setPage((dto.getPage() - 1) * dto.getSize());
        List<WmNewsVo> wmNewsVoList = wmNewsMapper.findListAndPage(dto);
        int count = wmNewsMapper.findListCount(dto);

        // 4.结果返回
        ResponseResult responseResult = new PageResponseResult(currentPage, dto.getSize(), count);
        responseResult.setData(wmNewsVoList);
        return responseResult;
    }

    @Autowired
    private WmUserMapper wmUserMapper;

    @Override
    public ResponseResult findWmNewsVo(Integer id) {
        // 1.检查参数
        if(id == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        // 2.查询文章信息
        WmNews wmNews = getById(id);
        if(wmNews == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        // 3.查询用户信息
        WmUser wmUser = wmUserMapper.selectById(wmNews.getUserId());

        // 4.封装vo返回
        WmNewsVo vo = new WmNewsVo();
        // 5.属性拷贝
        BeanUtils.copyProperties(wmNews,vo);
        if(wmUser != null){
            vo.setAuthorName(wmUser.getName());
        }

        return ResponseResult.okResult(vo);
    }

    @Autowired
    private IArticleClient iArticleClient;
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public ResponseResult passOrFail(NewsAuthDto dto, Integer type) {
        if (dto == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        Integer id = dto.getId();
        String msg = dto.getMsg();

        WmNews wmNews = wmNewsMapper.selectById(id);
        if (wmNews == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "新闻不存在");
        }

        int status = type == 1 ? 9 : 2;
        wmNews.setStatus((short) status);
        wmNews.setReason(type == 1 ? "通过" : msg);
        int updateResult = wmNewsMapper.updateById(wmNews);
        if (updateResult < 1) {
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR, "新闻审核失败");
        }

        if (type == 1) {
            ArticleDto articleDto = autoScanService.wmNews2Dto(wmNews);
            ResponseResult responseResult = iArticleClient.saveArticle(articleDto);
            if (responseResult == null || responseResult.getCode() != 200) {
                throw new RuntimeException("文章保存失败");
            }
        }

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);

    }

    @Autowired
    private IScheduleClient scheduleClient;

    private Boolean addToTask(Integer newsId, Long executeTime) {
        Task task = new Task();
        task.setExecuteTime(executeTime);

        WmNews wmNews = new WmNews();
        wmNews.setId(newsId);
        task.setParameters(ProtostuffUtil.serialize(wmNews));
        ResponseResult responseResult = scheduleClient.addTask(task);
        if (responseResult != null && responseResult.getCode() == 200) {
            return true;
        }
        return false;
    }


    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean addMaterial(Integer newsId, List<String> imagesList, Integer type) {
        if (CollectionUtils.isEmpty(imagesList)) {
            return true;
        }

        for (String url : imagesList) {
            if (StringUtils.isEmpty(url)) {
                continue;
            }

            WmMaterial material = new WmMaterial();
            material.setUserId(WmUserThreadLocal.get().getId());
            material.setUrl(url);
            material.setType((short) 0);
            material.setIsCollection((short) 0);
            material.setCreatedTime(new Date());
            material.setId(newsId);

            int insert = wmMaterialMapper.insert(material);
            if (insert < 1) {
                throw new RuntimeException("素材添加失败");
            }

            WmNewsMaterial newsMaterial = new WmNewsMaterial();
            newsMaterial.setType(type.shortValue());
            newsMaterial.setOrd((short) 1);
            newsMaterial.setNewsId(newsId);
            newsMaterial.setMaterialId(material.getId());
            int insert1 = wmNewsMaterialMapper.insert(newsMaterial);
            if (insert1 < 1) {
                throw new RuntimeException("新闻素材添加失败");
            }
        }
        return true;
    }

    private List<String> getCoverImages(short type,List<String> contentImages,List<String> images) {
        if (type == -1) {
            int size = contentImages.size();

            if (size >= 3) {
                return contentImages.subList(0,3);
            } else if (size == 2) {
                return contentImages.subList(0,1);
            } else if (size == 1) {
                List<String> urlList = new ArrayList<>();
                String s = contentImages.get(0);
                urlList.add(s);
                return urlList;
            }
        }
        return images;
    }

    private List<String> getContentImages(String content) {
        if (StringUtils.isEmpty(content)) {
            return new ArrayList<>();
        }

        List<String> urlList = new ArrayList<>();

        List<Map> maps = JSON.parseArray(content, Map.class);

        for (Map item : maps) {
            if (CollectionUtils.isEmpty(item)) {
                return new ArrayList<>();
            }

            String type = (String) item.get("type");
            if ("image".equals(type)) {
                String value = (String) item.get("value");
                urlList.add(value);
            }
        }

        return urlList;
    }

    private WmNews getNews(WmNewsDto wmNewsDto) {
        if (wmNewsDto == null) {
            return null;
        }
        WmNews wmNews = new WmNews();
        //自动赋值
        BeanUtils.copyProperties(wmNewsDto,wmNews);
        //处理差异字段
        wmNews.setUserId(WmUserThreadLocal.get().getId());
        wmNews.setCreatedTime(new Date());
        wmNews.setEnable((short) 1);

        List<String> images = wmNewsDto.getImages();
        if (!CollectionUtils.isEmpty(images)) {
            String join = StringUtils.join(images, ",");
            wmNews.setImages(join);
        }

        if (wmNews.getType() == -1) {
            wmNews.setType(null);
        }

        return wmNews;
    }
}
